<?php
namespace app\service;
use app\exception\ErrnoPlus;
use app\model\AdminPathinfoAccountModel;
use app\model\AdminPathinfoModel;
use share\service\cache\CommonCacheKeyService;
use share\exception\ApiException;
use share\service\BaseModelService;
use share\service\RedisService;
use share\utils\Helper;

class AdminPathinfoService extends BaseModelService{

    CONST PATH_TYPE_OF_PAGE = 1;
    CONST PAHT_TYPE_OF_API  = 0;

    public  static function getModel()
    {
        return new AdminPathinfoModel;
    }

    public static function getAllAuth($filter = []){
        $data =  AdminPathinfoAccountModel::all($filter);
        return AdminPathinfoAccountModel::formatCollectionData($data);
    }

    public static function delAllAuth($filter = []){
        return AdminPathinfoAccountModel::destroy($filter); 
    }
    

    public static function bulkAddAuth($items){
        return AdminPathinfoAccountModel::insertAll($items);
    }
    public static function getAllBaseApiPathInfo(){
        $key = CommonCacheKeyService::getCacheKey(CommonCacheKeyService::CACHE_KEY_LOGIN_ACCOUNT_API_PATH);
        $data = RedisService::instance(RedisService::CACHE_DB_BASE)->getJson($key);
        if(empty($data)){
            $filter = [
                'path_type' => self::PAHT_TYPE_OF_API,
                'path_info' => ['<>',''],
            ];
            $allData = self::getAllByFilter($filter);
            if(!$allData){
                return null;
            }
            $data = Helper::listArrayColumn($allData,['id','path_info','method','check_login','check_auth']);
            RedisService::instance(RedisService::CACHE_DB_BASE)->setJson($key,$data,3600);
        }
        return $data;
    }

    public static function delAllBaseApiPathInfoByCache(){
        $key = CommonCacheKeyService::getCacheKey(CommonCacheKeyService::CACHE_KEY_LOGIN_ACCOUNT_API_PATH);
        RedisService::instance(RedisService::CACHE_DB_BASE)->del($key);
    }

    /**
     * 获取用户权限缓存
     */
    public static function getAllUserAuthListByCache($uid){
        $key = self::getCacheKeyOfAdminUserAuth($uid);
        $data = RedisService::instance(RedisService::CACHE_DB_BASE)->getJson($key);
        if(empty($data)){
            $filter = [
                'aid' => $uid,
            ];
            $allData = self::getAllAuth($filter);
            if(!$allData){
                return null;
            }
            $data = array_column($allData,'rid');
            RedisService::instance(RedisService::CACHE_DB_BASE)->setJson($key,$data,3600);
        }
        return $data;
    }

    /**
     * 删除用户权限缓存
     */
    public static function delAllUserCacheOfAuthList($uid){
        $key = self::getCacheKeyOfAdminUserAuth($uid);
        RedisService::instance(RedisService::CACHE_DB_BASE)->del($key);
    }

    public static function getCacheKeyOfAdminUserAuth($uid){
        return CommonCacheKeyService::getCacheKey(CommonCacheKeyService::CACHE_KEY_LOGIN_ACCOUNT_USER_API_PATH ,['uid' =>$uid]);
    }

    /**
     * 删除用户权限
     */
    public static function delAllAuthListByUser($uid){
        self::delAllAuth([
            'aid' => $uid,
        ]);
        return self::delAllUserCacheOfAuthList($uid);
    }

    /**
     * 检查是否需要登录
     */
    public static function isNeedLogin($path,$method){
        $data = self::getAllBaseApiPathInfo();  
        $pathInfo = Helper::filterOne($data,[
            'path_info' => $path,
            'method' => $method,    
        ]);
        if(empty($pathInfo)){
            throw new ApiException("当前接口不开放访问".$method." ".$path,ErrnoPlus::COMMON_ERROR);
        }
        return $pathInfo['check_login'] === 0 ? false : true;
    }

    /**
     * 检查是否包含权限
     * @return  bool
     */
    public static function hasApiPremission($userInfo,$path,$method){
        $data = self::getAllBaseApiPathInfo();
        $pathInfo = Helper::filterOne($data,[
            'path_info' => $path,
            'method' => $method,    
        ]);
        if(empty($pathInfo)){
            throw new ApiException("无权访问该接口",ErrnoPlus::COMMON_ERROR);
        }
        if($pathInfo['check_auth'] === 0){
            return true;
        }
        $authList = self::getAllUserAuthListByCache($userInfo['id']);
        if(!is_array($authList)){
            return false;
        }
        return in_array($pathInfo['id'],$authList);
    }

    /**
     * 获取用户的权限关联信息
     */
    public static function getAllRoleInfoByUser($uid){
        $authList = self::getAllAuth([
            'aid' => $uid,
        ]);
        return $authList;
    }

    /**
     * 获取用户的权限关联信息
     */
    public static function setUseRoleInfo($uid,$pathIds){
        // // 已有的权限
        // $authList = self::getAllAuth([
        //     'aid' => $uid,
        // ]);
        $pathIds = Helper::arraySmartUnique($pathIds);
        $pathIds = array_filter(array_map('intval',$pathIds));
        if(count($pathIds) > 0){
            $pathInfo = self::getAllByFilter(['id' => ['in',$pathIds]]);
            //要赋值的权限不存在
            if(count($pathInfo) !== count($pathIds)){
                $existIds = array_column($pathInfo,'id');
                $errorIds = array_diff($pathIds,$existIds);
                throw new ApiException("path id ".json_encode($errorIds)." is not exist",ErrnoPlus::COMMON_ERROR);
            }
            // 已有的权限
            $authList = self::getAllAuth([
                'aid' => $uid,
            ]);
            $tn = time();
            $addInfo = [];
            $delIds = [];
            //之前无权限  直接新增     
            if(empty($authList)){
                foreach($pathIds as $rid){
                    $addInfo[] = [
                        'aid' => $uid,
                        'rid' => $rid,
                        'first_time' => $tn,
                        'modify_time' => $tn,
                    ];
                }
            }
            else{
                $accessIds = array_filter(array_map('intval',array_column($authList,'rid')));
                $addIds = array_diff($pathIds,$accessIds);
                foreach($addIds as $rid){
                    $addInfo[] = [
                        'aid' => $uid,
                        'rid' => $rid,
                        'first_time' => $tn,
                        'modify_time' => $tn,
                    ];
                }
                $delIds = array_diff($accessIds,$pathIds);
            }
            if(count($addInfo) > 0){
                self::bulkAddAuth($addInfo);
            }

            if(count($delIds) > 0){
                self::delAllAuth([
                    'aid' => $uid,
                    'rid' => ['in',$delIds],
                ]);
                self::delAllUserCacheOfAuthList($uid);
            }
        }
        else{
            self::delAllAuthListByUser($uid);
            return;
        }

        return $authList;
    }

    /**
     * 获取用户的页面权限
     */
    public static function getRoleInfoByUser($uid,$isRoot = false){
        $pathFilter = [
            'path_type' => self::PATH_TYPE_OF_PAGE,
        ];
        if(!$isRoot){
            
            $authList = self::getAllAuth(['aid' => $uid]);
            $pathIds = Helper::arraySmartUnique(array_column($authList,'rid'));
            if(count($pathIds) < 1){
                return [];
            }
            $pathFilter['id'] = [
                'in', $pathIds
            ];
        }       

        $pathList = self::getAllByFilter($pathFilter);    
        $pathList = Helper::arrayListReplaceKey($pathList,['path_info'=>'rule','icon_type'=>'iconType']);
        $children = [];
        $pids = Helper::arraySmartUnique(array_column($pathList,'pid'));
        foreach($pids as $pid){
            $children[$pid] = Helper::filter($pathList,['pid'=>$pid]);
        } 
        $root = [];
        self::makeDeepChildren($children,0,$root);
        return isset($root['children']) ? $root['children'] : [];
    }

    /**
     * 获取节点信息
     */
    public static function getAllPathInfoByType($pathType = null){
        $filter = [];
        if($pathType){
            $filter['path_type'] = $pathType;
        }
        $data = self::getAllByFilter($filter);
        $simpleData = Helper::listArrayColumn($data,['id','show'=>'name','pid']);
        $children = [];
        $pids = Helper::arraySmartUnique(array_column($simpleData,'pid'));
        foreach($pids as $pid){
            $children[$pid] = Helper::filter($simpleData,['pid'=>$pid]);
        } 
        $root = [];
        self::makeDeepChildren($children,0,$root);
        return isset($root['children']) ? $root['children'] : [];
    }

    /**
     * 生成树状结构 
     */
    public static function makeDeepChildren($data,$pid,& $tree){        
        if(isset($data[$pid])){
            $tree['children'] = $data[$pid];
            unset($data[$pid]);   // 防止自为父节点或互为父节点（有环图结构）导致的死循环
            foreach($tree['children'] as &$child){
                $children2 = self::makeDeepChildren($data,$child['id'],$child);
                if($children2){
                    $child['children'] = $children2;
                }
            }
        }
        else{
            $tree['children'] = [];
        }
    }

    public static function addPath($param){ 
        $item  = Helper::arrayCamelKeyToUnderscore($param);
        if(!isset($item['icon'])){ //icon 为 text
            $item['icon'] = "";
        }
        self::add($item);
    }

    public static function updatePath($param){        
        $id =  $param['id'];
        unset($param['id']);
        $origin = self::getBase($id);        
        if(empty($origin)){
            throw new ApiException("origin data is not exist",ErrnoPlus::COMMON_ERROR);
        }

        $item = Helper::arrayCamelKeyToUnderscore($param);

        $update = [];
        foreach($item as $key => $val){
            if($val != $origin[$key]){
                $update[$key] = $val;
            }
        }
        if(count($update) > 0){
            self::update($id,$update);
        }
    }

    public static function delPath($id){
        self::del($id);
    }

    public static function buildCondition($filter)
    {
        return [];
    }
   
}

